/* Editor.h
Copyright (c) 2008 Michael Zahniser
Please note the license terms (MIT license) at the end of this document.

Header file for the kwirki Editor class, which manages editing of a text file.

The editor does not know what sort of view the text is being displayed in: it
may be a console, or an SDL window, or something entirely different. All the
editor knows is the number of visible lines and the width of each line, plus
a functor for measuring the width of some given text.

For starters, kwirki will run in the command line, but this will allow it to
run in windowed mode instead very easily.
*/

#ifndef __MZ_EDITOR_H__
#define __MZ_EDITOR_H__

#include "_common/text.h"
#include "_common/ViewProperties.h"
#include "_common/Noncopyable.h"

#include <string>
#include <vector>

using std::string;
using std::vector;



class Editor : public Noncopyable {
public:
	// Constructor, specifying how the text width should be measured.
	Editor(const ViewProperties<text> &viewProperties);
	
	// Load the given file.
	void Open(const string &fileName);
	// Save the current file.
	void Save() const;
	// Get the current file's name.
	const string &FileName() const;
	
	// Get iterators to the beginnings of all the lines of text to display.
	// If the given row is out of bounds, the end of the file is returned.
	text::const_iterator Line(int row) const;
	
	// Get the index of the line that the cursor is on.
	int CursorLine() const;
	// Get the X position of the cursor within that line.
	int CursorX() const;
	
	// Handle the given input. The key code is in ncurses form.
	void HandleKey(int key);
	
	// Get the text of the link that the cursor is over (if any).
	const string &LinkText() const;
	// Move the cursor to the named anchor within this page, if it exists.
	void GoToAnchor(const string &name);
	
	
private:
	// Initialize this editor (no line wrapping calculated, scrolled to the top,
	// cursor at the top of the document).
	void Initialize();
	// Clear all the line wrapping data after the given point.
	void ClearWrapping(text::const_iterator it) const;
	// Make sure that we have line wrap marks for at least the given number of 
	// lines below the bottom of the display, unless at the end of the file.
	void PreScroll(int lineCount) const;
	// Add one line to the line wrap vector. Return false if we're at the end of
	// the file.
	bool WrapNextLine() const;
	// Move the cursor to the desired X.
	// Assume it >= lines.begin() and it < lines.end() - 1.
	void CursorToDesiredX(vector<text::mark>::const_iterator it);
	
	// Get an iterator to the line break entry for the line the cursor is in.
	vector<text::mark>::iterator CursorLineIt();
	vector<text::mark>::const_iterator CursorLineIt() const;
	
	// Scroll the view up or down by the given number of lines.
	void CursorUp(int lineCount = 1);
	void CursorDown(int lineCount = 1);
	
	// Move the cursor to the next link, scrolling as necessary.
	// If no links are found, keep the cursor where it is.
	void NextLink();
	
	
public:
	static const string &RootDirectory();
	
	
private:
	// The object to be used for measuring text.
	const ViewProperties<text> view;
	
	// The file being edited.
	text file;
	// The name of the file.
	string fileName;
	// The full path to the file.
	string filePath;
	
	// The cursor position within the file.
	text::iterator cursor;
	// The cursor's desired x position (defined by the text measure).
	mutable int cursorDesiredX;
	
	// We are scrolled so that this line is at the top of the display.
	mutable int scrollLine;
	// Beginnings of all lines to display.
	mutable vector<text::mark> lines;
};



#endif



/* Copyright (c) 2008 Michael Zahniser

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. */

